package ru.sgu.acm.dao;

import org.jacuzzi.core.DatabaseException;
import org.jacuzzi.core.GenericDaoImpl;
import ru.sgu.acm.database.DataSourceFactory;
import ru.sgu.acm.misc.Constants;
import ru.sgu.acm.model.Submit;

import java.util.List;

import static java.lang.String.format;

/**
 * Jacuzzi based imlementation of SubmitDao.
 *
 * @author Vitaly Goldshteyn (VitalyGoldstein@gmail.com)
 */
public class SubmitDaoImpl extends GenericDaoImpl<Submit, Long> implements SubmitDao {

    SubmitSourceDao submitSourceDao = new SubmitSourceDaoXmlRpcImpl();

    public SubmitDaoImpl() {
        super(DataSourceFactory.getDataSource());
    }

    @Override
    public void insert(Submit submit) {
        super.insert(submit);
    }

    public Submit extractPending() {
        long id = Constants.getContesterId();
        int size = getJacuzzi().execute("UPDATE Submits SET Status = ?, contesterId = ? " +
                "WHERE Status = ? ORDER BY priority DESC, Arrived LIMIT 1",
                Constants.getTestingStatus(), id, Constants.getPendingStatus());
        if (size == 1) {
            List<Submit> pendings = findBy("Status = ? AND contesterId = ? LIMIT 1",
                    Constants.getTestingStatus(), id);

            if (pendings.size() != 1) {
                throw new DatabaseException(format("Expected to fetch " +
                        "exactly one submit, but %d found", pendings.size()));
            }
            Submit submit = pendings.get(0);
            setupProblemProperties(submit);
            setupSource(submit);
            return submit;
        } else {
            if (size != 0) {
                throw new DatabaseException(format("Expected to update " +
                        "no more, than one submit, extracting pending submit"));
            }
        }
        return null;
    }

    private void setupProblemProperties(Submit submit) {
        String meta = getJacuzzi().findString("SELECT Meta FROM Problems WHERE Contest = ? AND ID = ?",
                submit.getContestId(), submit.getTaskId());
        submit.loadProblemProperties(meta);
    }

    private void setupSource(Submit submit) {
        submit.setSource(submitSourceDao.getSource(submit.getId()));
    }
}
